@isTest
private class NatoCaseStateTableTest {

	private static boolean fastTestMode = true;
	private static boolean superFastTestMode = true;
	
	private static final string Role_OE = 'Order Entry';
	private static final string Role_AP = 'Ad Production Rep';
	private static final string Role_SS = 'Sales/Customer Support';
	private static final string Role_OV = 'Order Validation';
	private static final string Role_QC = 'IOG OOR - AP - Rep';
	private static final string Role_QC2 = 'IOG OOR - QC - Rep';
	private static final string Role_Billing = 'Billing';
	private static final string Role_AASSales = 'SVP of National Sales';
	 
	private enum caseType {InsertionOrder, ChangeRequest}
	private static ID natoProfileId = null;
	private static Map<string,ID> natoRoleMap = null;
	private static Map<string,User> testUsers = new Map<string, User>();
	
	private static final Set<string> statuses = new Set<string>{
	NatoCaseStateTable.AP_Edit_to_OE ,
	NatoCaseStateTable.AP_Edit_to_OV  ,
	NatoCaseStateTable.AP_Query_to_SS  ,
	NatoCaseStateTable.AP_Release_Live  ,
	NatoCaseStateTable.AP_Response_to_QC  ,
	NatoCaseStateTable.AP_in_Progress  ,
	NatoCaseStateTable.Billing_Complete  ,
	NatoCaseStateTable.Billing_Query_to_SS  ,
	NatoCaseStateTable.Billing_in_Progress  ,
	NatoCaseStateTable.Future_Start_Date  ,
	NatoCaseStateTable.OC_Edit_to_OE  ,
	NatoCaseStateTable.OE_Edit_to_OV  ,
	NatoCaseStateTable.OE_Query_to_SS  ,
	NatoCaseStateTable.OE_Release_Live  ,
	NatoCaseStateTable.OE_Response_to_AP  ,
	NatoCaseStateTable.OE_Response_to_QC  ,
	NatoCaseStateTable.OE_With_Vendor  ,
	NatoCaseStateTable.OE_in_Progress  ,
	NatoCaseStateTable.OV_Pre_Fulfillment_to_SS  ,
	NatoCaseStateTable.OV_Query_to_SS  ,
	NatoCaseStateTable.OV_Response_to_AP  ,
	NatoCaseStateTable.OV_Response_to_OE  ,
	NatoCaseStateTable.OV_Response_to_QC  ,
	NatoCaseStateTable.OV_in_Progress  ,
	NatoCaseStateTable.QC_Edit_to_AP  ,
	NatoCaseStateTable.QC_Edit_to_OE  ,
	NatoCaseStateTable.QC_Edit_to_OV  ,
	NatoCaseStateTable.QC_Fulfilled  ,
	NatoCaseStateTable.QC_Query_to_SS  ,
	NatoCaseStateTable.QC_Release_Live  ,
	NatoCaseStateTable.QC_in_Progress  ,
	NatoCaseStateTable.Query_to_Client  ,
	NatoCaseStateTable.Ready_for_2nd_QC  ,
	NatoCaseStateTable.Ready_for_AP  ,
	NatoCaseStateTable.Ready_for_Billing  ,
	NatoCaseStateTable.Ready_for_OE  ,
	NatoCaseStateTable.Ready_for_OV  ,
	NatoCaseStateTable.Ready_for_QC  ,
	NatoCaseStateTable.Released_Live  ,
	NatoCaseStateTable.SS_Fulfilled  ,
	NatoCaseStateTable.SS_Response_to_AP  ,
	NatoCaseStateTable.SS_Response_to_Billing  ,
	NatoCaseStateTable.SS_Response_to_OE  ,
	NatoCaseStateTable.SS_Response_to_OV  ,
	NatoCaseStateTable.SS_Response_to_QC  ,
	NatoCaseStateTable.SS_With_Vendor  ,
	NatoCaseStateTable.Site_Issue  ,
	NatoCaseStateTable.Cancelled		
	};
	
	// **************************
	// Assignment Tests	
	// **************************
    static testMethod void testOVAssignment() {
    	Case c = CreateCasesInStatus(NatoCaseStateTable.Ready_for_OV, caseType.InsertionOrder, 1, null)[0];
    	UpdateCaseStatus(new List<Case>{c}, NatoCaseStateTable.OV_in_Progress, Role_OV);
    	c = [SELECT NATO_Rep_OV__c, Nato_Rep_SS__c from Case where ID = :c.ID];
    	System.assert(c.NATO_Rep_OV__c != null, 'Order Validation rep should not be empty');
    	System.assert(c.Nato_Rep_SS__c != null, 'Ad Production rep should not be empty');
	}
	/*
	// Disabling these tests since Round Robin might be turned off.
	// We could improve these tests by ensuring Round Robin is enabled with active users.
    static testMethod void testOEAssignment() {
    	Case c = CreateCasesInStatus(NatoCaseStateTable.OV_In_Progress, caseType.InsertionOrder, 1, null)[0];
    	UpdateCaseStatus(new List<Case>{c}, NatoCaseStateTable.Ready_For_OE, Role_OV);
    	c = [SELECT Order_Entry__c from Case where ID = :c.ID];
    	System.assert(c.Order_Entry__c != null, 'Order Entry rep should not be empty');

	}
    static testMethod void testAPAssignment() {
    	Case c = CreateCasesInStatus(NatoCaseStateTable.OE_In_Progress, caseType.InsertionOrder, 1, null)[0];
    	UpdateCaseStatus(new List<Case>{c}, NatoCaseStateTable.Ready_For_AP, Role_OE);
    	c = [SELECT Ad_Production__c from Case where ID = :c.ID];
    	System.assert(c.Ad_Production__c != null, 'Ad Production rep should not be empty');

	}*/
	
    static testMethod void testQCAssignment() {
    	Case c = CreateCasesInStatus(NatoCaseStateTable.Ready_for_QC, caseType.InsertionOrder, 1, null)[0];
    	UpdateCaseStatus(new List<Case>{c}, NatoCaseStateTable.QC_in_Progress, Role_QC);
    	c = [SELECT Quality_Control__c from Case where ID = :c.ID];
    	System.assert(c.Quality_Control__c != null, 'Quality Control rep should not be empty');

	}
    static testMethod void testQC2Assignment() {
    	Case c = CreateCasesInStatus(NatoCaseStateTable.Ready_for_2nd_QC, caseType.InsertionOrder, 1, null)[0];
    	UpdateCaseStatus(new List<Case>{c}, NatoCaseStateTable.QC_in_Progress, Role_QC);
    	c = [SELECT Nato_Rep_QC2__c from Case where ID = :c.ID];
    	System.assert(c.Nato_Rep_QC2__c != null, 'Quality Control rep 2 should not be empty');

	}
    static testMethod void testBillingAssignment() {
    	Case c = CreateCasesInStatus(NatoCaseStateTable.Ready_for_Billing, caseType.InsertionOrder, 1, null)[0];
    	UpdateCaseStatus(new List<Case>{c}, NatoCaseStateTable.Billing_in_Progress, Role_Billing);
    	c = [SELECT Billing__c from Case where ID = :c.ID];
    	System.assert(c.Billing__c != null, 'Billing rep should not be empty');
    }
    
	// **************************
	// ORDER VALIDATION TESTS
	// **************************
    static testMethod void testFutureStartDateWorkflow() {
    	string startingStatus = NatoCaseStateTable.Future_Start_Date;
    	string role = Role_OV;
    	
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.Ready_for_OE//,
    		//NatoCaseStateTable.Cancelled
    	};
    	 
    	Map<string,object> additionalFields = new Map<string,object>{'Future_Start_Date__c' => Date.today().addDays(-1)};
    	//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
    	VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
    }
    
    static testMethod void testReadyForOVStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.Ready_for_OV;
			string role = Role_OV;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OV_in_Progress,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    
    static testMethod void testOVInProgressStatusWorkflowIO() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OV_in_Progress;
			string role = Role_OV;
			 
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_OE,
				NatoCaseStateTable.OV_Pre_Fulfillment_to_SS,
				NatoCaseStateTable.OV_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
		}
    }
    
    static testMethod void testOVInProgressStatusWorkflowCR() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OV_in_Progress;
			string role = Role_OV;
			 
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_OE,
				NatoCaseStateTable.Ready_for_AP,
				NatoCaseStateTable.OV_Pre_Fulfillment_to_SS,
				NatoCaseStateTable.OV_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    
    static testMethod void testOVInProgressStatusWithFutureStartWorkflow() {
    	string startingStatus = NatoCaseStateTable.OV_in_Progress;
    	string role = Role_OV;
    	 
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.Future_Start_Date,
    		NatoCaseStateTable.OV_Pre_Fulfillment_to_SS,
    		NatoCaseStateTable.OV_Query_to_SS//,
    		//NatoCaseStateTable.Cancelled
    	};
    	Map<string,object> additionalFields = new Map<string,object>{'Future_Start_Date__c' => Date.today().addDays(1)};
    	VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
    	VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
    }

    static testMethod void testOEEditToOVStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OE_Edit_to_OV;
			string role = Role_OV;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OV_Response_to_OE,
				NatoCaseStateTable.OV_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testAPEditToOVStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.AP_Edit_to_OV;
			string role = Role_OV;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OV_Response_to_AP,
				NatoCaseStateTable.OV_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    static testMethod void testSSResponseToOVStatusWorkflowCR() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.SS_Response_to_OV;
			string role = Role_OV;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_OE,
				NatoCaseStateTable.Ready_for_AP,
				NatoCaseStateTable.OV_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);    	
		}
    }
    
    static testMethod void testSSResponseToOVStatusWorkflowCRFutureStart() {
    	string startingStatus = NatoCaseStateTable.SS_Response_to_OV;
    	string role = Role_OV;
    	
		// Test with future start date set
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.Ready_for_OE,
    		NatoCaseStateTable.Ready_for_AP,
    		NatoCaseStateTable.OV_Query_to_SS,
    		NatoCaseStateTable.Future_Start_Date//,
    		//NatoCaseStateTable.Cancelled
    	};
    	Map<string,object> additionalFields = new Map<string,object>{'Future_Start_Date__c' => Date.today().addDays(1)};
    	VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);    	
    }
    
    static testMethod void testSSResponseToOVStatusWorkflowIO() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.SS_Response_to_OV;
			string role = Role_OV;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_OE,
				NatoCaseStateTable.OV_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
		}
    }
    
    static testMethod void testSSResponseToOVStatusWorkflow3() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.SS_Response_to_OV;
			string role = Role_OV;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OV_Response_to_OE,
				NatoCaseStateTable.OV_Response_to_AP,
				NatoCaseStateTable.OV_Response_to_QC,
				NatoCaseStateTable.OV_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
	 
			Map<string,object> additionalFields = new Map<string,object>{
				'Order_Entry__c' => CreateUser(Role_OE).ID, 
				'Ad_Production__c' => CreateUser(Role_AP).ID, 
				'Quality_Control__c' => CreateUser(Role_QC).ID
				};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);    	
		}
    }
  
	// broken rep not set
    static testMethod void testSSResponseToOVStatusWorkflowWithFutureStart() {
    	string startingStatus = NatoCaseStateTable.SS_Response_to_OV;
    	string role = Role_OV;
    	
		// Test with future start date set
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.Ready_for_OE,
    		NatoCaseStateTable.OV_Query_to_SS,
    		NatoCaseStateTable.Future_Start_Date//,
    		//NatoCaseStateTable.Cancelled
    	};
    	Map<string,object> additionalFields = new Map<string,object>{'Future_Start_Date__c' => Date.today().addDays(1)};
    	VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
    	//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);    	
    }
	
	// *********************************    
	// ORDER ENTRY TESTS
	// *********************************    
    static testMethod void testReadyForOEStatusWorkflow() {
    	string startingStatus = NatoCaseStateTable.Ready_for_OE;
    	string role = Role_OE;
    	
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.OE_in_Progress//,
    		//NatoCaseStateTable.Cancelled
    	};
    	 
    	VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
    	//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
    }
    	
    static testMethod void testOEInProgressStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OE_In_Progress;
			string role = Role_OE;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OE_with_vendor,
				NatoCaseStateTable.OE_release_live,
				NatoCaseStateTable.Ready_for_AP,
				NatoCaseStateTable.Ready_for_QC,
				NatoCaseStateTable.OE_edit_to_OV,
				NatoCaseStateTable.OE_query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testOEWithVendorStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OE_With_Vendor;
			string role = Role_OE;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OE_release_live,
				NatoCaseStateTable.Ready_for_AP,
				NatoCaseStateTable.Ready_for_QC,
				NatoCaseStateTable.OE_edit_to_OV,
				NatoCaseStateTable.OE_query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
	  
    static testMethod void testSSResponseToOEStatusWorkflow1() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.SS_Response_to_OE;
			string role = Role_OE;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OE_with_vendor,
				NatoCaseStateTable.OE_release_live,
				NatoCaseStateTable.Ready_for_AP,
				NatoCaseStateTable.Ready_for_QC,
				NatoCaseStateTable.OE_edit_to_OV,
				NatoCaseStateTable.OE_query_to_SS,
				NatoCaseStateTable.Cancelled
			};

			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    
    static testMethod void testSSResponseToOEStatusWorkflow2() {
    	string startingStatus = NatoCaseStateTable.SS_Response_to_OE;
    	string role = Role_OE;
    	
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.OE_with_vendor,
    		NatoCaseStateTable.OE_edit_to_OV,
    		NatoCaseStateTable.OE_query_to_SS,
    		NatoCaseStateTable.OE_response_to_AP,
    		NatoCaseStateTable.OE_response_to_QC//,
    		//NatoCaseStateTable.Cancelled
    	};

    	Map<string,object> additionalFields = new Map<string,object>{
    		'Ad_Production__c' => CreateUser(Role_AP).ID, 
    		'Quality_Control__c' => CreateUser(Role_QC).ID
    		};
    	VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
    	//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
    }

    static testMethod void testOVResponseToOEStatusWorkflow1() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OV_Response_to_OE;
			string role = Role_OE;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OE_with_vendor,
				NatoCaseStateTable.OE_release_live,
				NatoCaseStateTable.Ready_for_AP,
				NatoCaseStateTable.Ready_for_QC,
				NatoCaseStateTable.OE_edit_to_OV,
				NatoCaseStateTable.OE_query_to_SS,
				NatoCaseStateTable.Cancelled
			};

			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testOVResponseToOEStatusWorkflow2() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OV_Response_to_OE;
			string role = Role_OE;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OE_with_vendor,
				NatoCaseStateTable.OE_edit_to_OV,
				NatoCaseStateTable.OE_query_to_SS,
				NatoCaseStateTable.OE_response_to_AP,
				NatoCaseStateTable.OE_Response_to_QC,
				NatoCaseStateTable.Cancelled
			};

			Map<string,object> additionalFields = new Map<string,object>{
				'Ad_Production__c' => CreateUser(Role_AP).ID, 
				'Quality_Control__c' => CreateUser(Role_QC).ID
				};
			//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
		}
    }

    static testMethod void testQCEditToOEStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.QC_Edit_to_OE;
			string role = Role_OE;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OE_edit_to_OV,
				NatoCaseStateTable.OE_query_to_SS,
				NatoCaseStateTable.OE_Response_to_QC,
				NatoCaseStateTable.Cancelled
			};

			Map<string,object> additionalFields = new Map<string,object>{
				'Quality_Control__c' => CreateUser(Role_QC).ID
				};
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
		}
    }

    static testMethod void testAPEditToOEStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.AP_Edit_to_OE;
			string role = Role_OE;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.OE_edit_to_OV,
				NatoCaseStateTable.OE_query_to_SS,
				NatoCaseStateTable.OE_Response_to_AP,
				NatoCaseStateTable.Cancelled
			};

			Map<string,object> additionalFields = new Map<string,object>{
				'Ad_Production__c' => CreateUser(Role_AP).ID
				};
			//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
		}
    }
   
    static testMethod void testOEReleaseLiveStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OE_Release_Live;
			
			List<Case> cases = CreateCasesInStatus(startingStatus, caseType.ChangeRequest, 1, null);
			string status = [Select status from case where ID = :cases[0].id][0].status;
			System.assert(status == NatoCaseStateTable.Ready_for_QC, 'The case should have automatically moved to the Ready for QC status');		
		}
    }

	// *********************************    
	// AD PRODUCTION TESTS
	// *********************************    
    static testMethod void testReadyForAPStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.Ready_for_AP;
			string role = Role_AP;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.AP_in_Progress,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testAPInProgressStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.AP_in_Progress;
			string role = Role_AP;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_QC,
				NatoCaseStateTable.AP_Release_Live,
				NatoCaseStateTable.AP_Edit_to_OV,
				NatoCaseStateTable.AP_Edit_to_OE,
				NatoCaseStateTable.AP_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};

			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testSSResponseToAPStatusWorkflow() {
    	string startingStatus = NatoCaseStateTable.SS_Response_to_AP;
    	string role = Role_AP;
    	
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.Ready_for_QC,
    		NatoCaseStateTable.AP_Release_Live,
    		NatoCaseStateTable.AP_Edit_to_OV,
    		NatoCaseStateTable.AP_Edit_to_OE,
    		NatoCaseStateTable.AP_Query_to_SS//,
    		//NatoCaseStateTable.Cancelled
    	};
    	 
    	//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
    	VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
    }

    static testMethod void testOVResponseToAPStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OV_Response_to_AP;
			string role = Role_AP;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_QC,
				NatoCaseStateTable.AP_Release_Live,
				NatoCaseStateTable.AP_Edit_to_OV,
				NatoCaseStateTable.AP_Edit_to_OE,
				NatoCaseStateTable.AP_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testOEResponseToAPStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OE_Response_to_AP;
			string role = Role_AP;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_QC,
				NatoCaseStateTable.AP_Release_Live,
				NatoCaseStateTable.AP_Edit_to_OV,
				NatoCaseStateTable.AP_Edit_to_OE,
				NatoCaseStateTable.AP_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};

			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testQCEditToAPStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.QC_Edit_to_AP;
			string role = Role_AP;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.AP_Response_to_QC,
				NatoCaseStateTable.AP_Edit_to_OV,
				NatoCaseStateTable.AP_Edit_to_OE,
				NatoCaseStateTable.AP_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			Map<string,object> additionalFields = new Map<string,object>{
				'Quality_Control__c' => CreateUser(Role_QC).ID
				};
			//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
		}
    }
    
    static testMethod void testAPReleaseLiveStatusWorkflow() {
    	string startingStatus = NatoCaseStateTable.AP_Release_Live;
    	
		List<Case> cases = CreateCasesInStatus(startingStatus, caseType.InsertionOrder, 1, null);
		string status = [Select status from case where ID = :cases[0].id][0].status;
		System.assert(status == NatoCaseStateTable.Ready_for_QC, 'The case should have automatically moved to the Ready for QC status');		
    }
    
	// *********************************    
	// QUALITY CONTROL TESTS
	// *********************************    
    static testMethod void testReadyForQCStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.Ready_for_QC;
			string role = Role_QC;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.QC_in_Progress,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    static testMethod void testQCInProgressStatusWorkflowChange() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.QC_in_Progress;
			string role = Role_QC;
					
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.QC_Release_Live,
				NatoCaseStateTable.QC_Fulfilled,
				NatoCaseStateTable.QC_Edit_to_OV,
				NatoCaseStateTable.QC_Edit_to_OE,
				NatoCaseStateTable.QC_Edit_to_AP,
				NatoCaseStateTable.QC_Query_to_SS,
				NatoCaseStateTable.Site_Issue,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    
    static testMethod void testQCInProgressStatusWorkflowChangeReleased() {
    	string startingStatus = NatoCaseStateTable.QC_in_Progress;
    	string role = Role_QC;
    	    	
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.QC_Fulfilled,
    		NatoCaseStateTable.QC_Edit_to_OV,
    		NatoCaseStateTable.QC_Edit_to_OE,
    		NatoCaseStateTable.QC_Edit_to_AP,
    		NatoCaseStateTable.QC_Query_to_SS,
    		NatoCaseStateTable.Site_Issue,
    		NatoCaseStateTable.Ready_for_2nd_QC//,
    		//NatoCaseStateTable.Cancelled
    	};
    	 
    	Map<string,object> additionalFields = new Map<string,object>{
    		'Released_Live_Date__c' => DateTime.now()
    		};

    	VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
    }

    static testMethod void testQCInProgressStatusWorkflowIOReleased() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.QC_in_Progress;
			string role = Role_QC;
					
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_Billing,
				NatoCaseStateTable.QC_Fulfilled,
				NatoCaseStateTable.QC_Edit_to_OV,
				NatoCaseStateTable.QC_Edit_to_OE,
				NatoCaseStateTable.QC_Edit_to_AP,
				NatoCaseStateTable.QC_Query_to_SS,
				NatoCaseStateTable.Site_Issue,
				NatoCaseStateTable.Ready_for_2nd_QC,
				NatoCaseStateTable.Cancelled
			};

			Map<string,object> additionalFields = new Map<string,object>{
				'Released_Live_Date__c' => DateTime.now()
				};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
		}
    }

    static testMethod void testSSResponseToQCStatusWorkflowChange() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.SS_Response_to_QC;
			string role = Role_QC;
					
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.QC_Release_Live,
				NatoCaseStateTable.QC_Fulfilled,
				NatoCaseStateTable.QC_Edit_to_OV,
				NatoCaseStateTable.QC_Edit_to_OE,
				NatoCaseStateTable.QC_Edit_to_AP,
				NatoCaseStateTable.QC_Query_to_SS,
				NatoCaseStateTable.Site_Issue,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    
    
    static testMethod void testOVResponseToQCStatusWorkflowChangeReleased() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OV_Response_to_QC;
			string role = Role_QC;
					
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.QC_Fulfilled,
				NatoCaseStateTable.QC_Edit_to_OV,
				NatoCaseStateTable.QC_Edit_to_OE,
				NatoCaseStateTable.QC_Edit_to_AP,
				NatoCaseStateTable.QC_Query_to_SS,
				NatoCaseStateTable.Site_Issue,
				NatoCaseStateTable.Ready_for_2nd_QC,
				NatoCaseStateTable.Cancelled
			};
			 
			Map<string,object> additionalFields = new Map<string,object>{
				'Released_Live_Date__c' => DateTime.now()
				};

			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
		}
    }

    static testMethod void testOEResponseToQCStatusWorkflowIO() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OE_Response_to_QC;
			string role = Role_QC;
					
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.QC_Release_Live,
				NatoCaseStateTable.QC_Fulfilled,
				NatoCaseStateTable.QC_Edit_to_OV,
				NatoCaseStateTable.QC_Edit_to_OE,
				NatoCaseStateTable.QC_Edit_to_AP,
				NatoCaseStateTable.QC_Query_to_SS,
				NatoCaseStateTable.Site_Issue,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
		}
    }

    static testMethod void testAPResponseToQCStatusWorkflowIOReleased() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.AP_Response_to_QC;
			string role = Role_QC;
					
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_Billing,
				NatoCaseStateTable.QC_Fulfilled,
				NatoCaseStateTable.QC_Edit_to_OV,
				NatoCaseStateTable.QC_Edit_to_OE,
				NatoCaseStateTable.QC_Edit_to_AP,
				NatoCaseStateTable.QC_Query_to_SS,
				NatoCaseStateTable.Site_Issue,
				NatoCaseStateTable.Ready_for_2nd_QC,
				NatoCaseStateTable.Cancelled
			};

			Map<string,object> additionalFields = new Map<string,object>{
				'Released_Live_Date__c' => DateTime.now()
				};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
		}
    }
        
    static testMethod void testReadyFor2ndQCStatusWorkflowIO() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.Ready_for_2nd_QC;
			string role = Role_QC;
					
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.QC_in_Progress,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testSiteIssueStatusWorkflowIO() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.Site_Issue;
			string role = Role_QC;

			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_Billing,
				NatoCaseStateTable.QC_Fulfilled,
				NatoCaseStateTable.QC_Edit_to_OV,
				NatoCaseStateTable.QC_Edit_to_OE,
				NatoCaseStateTable.QC_Edit_to_AP,
				NatoCaseStateTable.QC_Query_to_SS,
				NatoCaseStateTable.Ready_for_2nd_QC,
				NatoCaseStateTable.Cancelled
			};

			Map<string,object> additionalFields = new Map<string,object>{
				'Released_Live_Date__c' => DateTime.now()
				};
							 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    
    static testMethod void testQCReleaseLiveStatusWorkflowIO() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.QC_Release_Live;
			string role = Role_QC;
					
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Ready_for_Billing,
				NatoCaseStateTable.QC_Fulfilled,
				NatoCaseStateTable.QC_Edit_to_OV,
				NatoCaseStateTable.QC_Edit_to_OE,
				NatoCaseStateTable.QC_Edit_to_AP,
				NatoCaseStateTable.QC_Query_to_SS,
				NatoCaseStateTable.Site_Issue,
				NatoCaseStateTable.Ready_for_2nd_QC,
				NatoCaseStateTable.Cancelled
			};

			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
		}
    }

	// *********************************    
	// SALES SUPPORT TESTS
	// *********************************    
    static testMethod void testOVPreFulfillmenttoSSStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OV_Pre_Fulfillment_to_SS;
			string role = Role_SS;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Query_to_Client,
				NatoCaseStateTable.Ready_for_OE,
				NatoCaseStateTable.SS_With_Vendor,
				NatoCaseStateTable.Future_Start_Date,
				NatoCaseStateTable.Cancelled
			};
			 
			Map<string,object> additionalFields = new Map<string,object>{'Future_Start_Date__c' => Date.today().addDays(1)};
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    
    static testMethod void testOVQuerytoSSStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.OV_Query_to_SS;
			string role = Role_SS;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Query_to_Client,
				NatoCaseStateTable.SS_Response_to_OV,
				NatoCaseStateTable.Cancelled
			};
			 
			//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testOEQuerytoSSStatusWorkflow() {
    	string startingStatus = NatoCaseStateTable.OE_Query_to_SS;
    	string role = Role_SS;
    	
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.Query_to_Client,
    		NatoCaseStateTable.SS_Response_to_OE,
    		NatoCaseStateTable.Cancelled
    	};
    	 
    	VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
    	//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
    }

    static testMethod void testAPQuerytoSSStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.AP_Query_to_SS;
			string role = Role_SS;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Query_to_Client,
				NatoCaseStateTable.SS_Response_to_AP,
				NatoCaseStateTable.Cancelled
			};
			 
			//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    static testMethod void testQCQuerytoSSStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.QC_Query_to_SS;
			string role = Role_SS;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Query_to_Client,
				NatoCaseStateTable.SS_Response_to_QC,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }
    
    static testMethod void testQueryToClientWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.Query_to_Client;
			string role = Role_SS;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.SS_Response_to_QC,
				NatoCaseStateTable.SS_Response_to_OV,
				NatoCaseStateTable.SS_Response_to_AP,
				NatoCaseStateTable.SS_Response_to_QC,
				NatoCaseStateTable.Ready_for_OE,
				NatoCaseStateTable.Future_Start_Date,		
				NatoCaseStateTable.Cancelled
			};
		
			Map<string,object> additionalFields = new Map<string,object>{
				'Ad_Production__c' => CreateUser(Role_AP).ID, 
				'Quality_Control__c' => CreateUser(Role_QC).ID,
				'Future_Start_Date__c' => Date.today().addDays(1)
				};
				
			//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, additionalFields);
		}
    }
    
    static testMethod void testBillingQuerytoSSStatusWorkflow() {
    	string startingStatus = NatoCaseStateTable.Billing_Query_to_SS;
    	string role = Role_SS;
    	
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.Query_to_Client,
    		NatoCaseStateTable.SS_Response_to_Billing//,
    		//NatoCaseStateTable.Cancelled
    	};
    	 
    	VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
    	//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
    }
    
    static testMethod void testBillingCompleteStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.Billing_Complete;
			string role = Role_SS;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.SS_Fulfilled,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

    static testMethod void testQCFulfilledStatusWorkflow() {
    	string startingStatus = NatoCaseStateTable.QC_Fulfilled;
    	string role = Role_SS;
    	
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.SS_Fulfilled//,
    		//NatoCaseStateTable.Cancelled
    	};
    	 
    	//VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
    	VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
    }

    static testMethod void testSSWithVendorStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.SS_With_Vendor;
			string role = Role_SS;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Query_to_Client,
				NatoCaseStateTable.Ready_for_OE,
				NatoCaseStateTable.Future_Start_Date,
				NatoCaseStateTable.Cancelled
			};
			 
			Map<string,object> additionalFields = new Map<string,object>{'Future_Start_Date__c' => Date.today().addDays(1)};
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, additionalFields);
			//VerifyValidStatuses(startingStatus, caseType.ChangeRequest, possibleNextStatus, role, null);
		}
    }

	// *********************************    
	// BILLING TESTS
	// *********************************    
    
    static testMethod void testReadyForBillingStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.Ready_for_Billing;
			string role = Role_Billing;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Billing_in_Progress,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
		}
    }

    static testMethod void testBillingInProgressStatusWorkflow() {
    	string startingStatus = NatoCaseStateTable.Billing_in_Progress;
    	string role = Role_Billing;
    	
    	Set<string> possibleNextStatus = new Set<string>{
    		NatoCaseStateTable.Billing_Complete,
    		NatoCaseStateTable.Billing_Query_to_SS//,
    		//NatoCaseStateTable.Cancelled
    	};
    	 
    	VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
    }

    static testMethod void testSSResponseToBillingStatusWorkflow() {
		if(!superFastTestMode)
		{
			string startingStatus = NatoCaseStateTable.SS_Response_to_Billing;
			string role = Role_Billing;
			
			Set<string> possibleNextStatus = new Set<string>{
				NatoCaseStateTable.Billing_Complete,
				NatoCaseStateTable.Billing_Query_to_SS,
				NatoCaseStateTable.Cancelled
			};
			 
			VerifyValidStatuses(startingStatus, caseType.InsertionOrder, possibleNextStatus, role, null);
		}
    }

//*************************************************************
    // Private Methods
	private static void VerifyValidStatuses(string startStatus, caseType ctype, Set<string> expectedValidStatuses, string userRole, Map<string, object> additionalValues){
		
		Set<string> statusesToTest;
				
		if(fastTestMode)
			statusesToTest = expectedValidStatuses;
		else
			statusesToTest = statuses;
		
		// Don't test moving to the same state		
		statusesToTest.remove(startStatus);
				
		List<string> failures = new List<string>();
		List<Case> cases = CreateCasesInStatus(startStatus, ctype, statusesToTest.size(), additionalValues);

		integer caseIdx = 0;		
		for(string newStatus : statusesToTest){
			cases[caseIdx].Status = newStatus;				
			caseIdx++;
		}

		Database.SaveResult[] lsr;
		
		if(null != userRole){
			User u = CreateUser(userRole);
			System.runAs(u){
				lsr = Database.update(cases, false);
			}
		}else{
			lsr = Database.update(cases, false);
		}
		
		for(integer i=0; i < lsr.size(); i++){
			Database.SaveResult sr = lsr[i];
			Case c = cases[i];
			
			if(!expectedValidStatuses.contains(c.status) && sr.isSuccess())
				failures.add('Changing case status from "' + startStatus + '" to "' + c.status + '" succeeded. It should have failed.');
			if(expectedValidStatuses.contains(c.status) && !sr.isSuccess()){
				// Ignore issues with closing cases by non-owners
				if(!sr.getErrors()[0].getMessage().contains('You can only close a case that is assigned to yourself'))
					failures.add('Changing case status from "' + startStatus + '" to "' + c.status + '" failed. It should have succeeded. Error: ' + sr.getErrors()[0].getMessage());
			}			
		}
		
		if(failures.size() > 0){
			string errorMessage = failures.size() + ' errors. ';
			for(string f: failures){
				errorMessage += f;
				system.debug(Logginglevel.error, f);
			}
			system.assert(false, errorMessage);
		}	
	}

	private static List<Case> CreateCasesInStatus(string status, caseType ctype, integer numberToCreate, Map<string, object> additionalValues){
	
        Account a = new Account();
        a.Name = 'Unit Test Account';
        a.RecordTypeId = RecordTypeHelper.GetRecordTypeIDByDevName('Account', 'Advanced_Ad_Solutions');
		System.runAs(CreateUser(Role_SS)){
			insert a;
		}
	
		List<Case> cases = new List<Case>();
		for(integer i=0; i < numberToCreate; i++){
			Case c = new Case();
			if(ctype == caseType.InsertionOrder)
				c.RecordTypeId = RecordTypeHelper.GetRecordTypeId('Case', 'National Ops - Insertion Order');
			else        
	        	c.RecordTypeId = RecordTypeHelper.GetRecordTypeId('Case', 'National Ops - Change Request');
				
			c.Nato_Rep_SS__c = CreateUser(Role_SS).id;

            c.AccountId = a.Id;
            c.Priority_Reason__c = 'Other';
            c.Billing_Frequency__c = 'Upfront';
            c.Term__c = 12;
            c.Business_Name__c = 'Unit Test Business';
            c.Contract_Type__c = 'New';
            c.number_of_CIDs__c = 2;
            c.NATO_num_of_Products__c = 2;
            c.Keyed_In_AF__c = Date.Today();
            c.AF_Customer_ID__c = '0';
			
			cases.add(c);			
		}
			
		System.runAs(CreateUser(Role_OV)){
			insert(cases);
		}
		//string currentStatus = [Select status from Case where ID = :c.ID][0].status;
		//System.AssertEquals(currentStatus, NatoCaseStateTable.Ready_for_OV);
		
		MoveCasesToStatus(cases, status);
					
		if(null != additionalValues){
			for(Case c : cases){
				for(string fieldName : additionalValues.keySet())
					c.put(fieldName, additionalValues.get(fieldName));					
			}
			System.runAs(CreateUser(Role_OV)){
				update(cases);
			}
		}

		return cases;				
	}
	/*
	private static void MoveCasesToStatusOld(List<Case> cases, string status){
		// Order Validation
    	if(status == NatoCaseStateTable.Future_Start_Date){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		UpdateCaseField(cases, 'Future_Start_Date__c', Date.today().addDays(1));
    		UpdateCaseStatus(cases, status, Role_OV);    		
		}else if(status == NatoCaseStateTable.Ready_for_OV){
			// Nothing to do
    	}else if(status == NatoCaseStateTable.OV_in_Progress){
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_Edit_to_OV){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.AP_Edit_to_OV){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_in_Progress);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.QC_Edit_to_OV){
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_OV){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		
    		
    	// Order Entry
		}else if(status == NatoCaseStateTable.Ready_for_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_in_Progress){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Ready_for_OE);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.OE_With_Vendor){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		
    	}else if(status == NatoCaseStateTable.OV_Response_to_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_Edit_to_OV);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.QC_Edit_to_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_in_Progress);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.AP_Edit_to_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_in_Progress);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.OE_Release_Live){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    		    		
    	// Ad Production
		}else if(status == NatoCaseStateTable.Ready_for_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.AP_in_Progress){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Ready_for_AP);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		
    	}else if(status == NatoCaseStateTable.OV_Response_to_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_Edit_to_OV);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_Response_to_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_Edit_to_OE);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.QC_Edit_to_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_in_Progress);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.AP_Release_Live){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_in_Progress);
    		UpdateCaseStatus(cases, status, Role_AP);    		

    	// Quality Control
		}else if(status == NatoCaseStateTable.Ready_for_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.QC_in_Progress){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Ready_for_QC);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		
    	}else if(status == NatoCaseStateTable.OV_Response_to_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Edit_to_OV);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_Response_to_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Edit_to_OE);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.AP_Response_to_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Edit_to_AP);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.Ready_for_2nd_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Release_Live);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.Site_Issue){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Release_Live);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.QC_Release_Live){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_in_Progress);
    		UpdateCaseStatus(cases, status, Role_QC);    		

    	// Sales Support
		}else if(status == NatoCaseStateTable.OV_Pre_Fulfillment_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OV_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.AP_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_in_Progress);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.QC_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_in_Progress);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.Query_to_Client){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.Billing_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Billing_in_Progress);
    		UpdateCaseStatus(cases, status, Role_Billing);    		
    	}else if(status == NatoCaseStateTable.Billing_Complete){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Billing_in_Progress);
    		UpdateCaseStatus(cases, status, Role_Billing);    		
    	}else if(status == NatoCaseStateTable.QC_Fulfilled){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Release_Live);
    		UpdateCaseStatus(cases, status, Role_QC);    		

    	// Billing
		}else if(status == NatoCaseStateTable.Ready_for_Billing){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Release_Live);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.Billing_in_Progress){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Ready_for_Billing);
    		UpdateCaseStatus(cases, status, Role_Billing);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_Billing){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Billing_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		

		// Other
    	}else if(status == NatoCaseStateTable.Cancelled){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else{
    		system.assert(false, 'MoveCaseToStatus does not support status: ' + status);
    	}    	
    	
	}
    	*/
	private static void MoveCasesToStatus(List<Case> cases, string status){
		// Order Validation
    	if(status == NatoCaseStateTable.Future_Start_Date){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		UpdateCaseField(cases, 'Future_Start_Date__c', Date.today().addDays(1));
    		UpdateCaseStatus(cases, status, Role_OV);    		
		}else if(status == NatoCaseStateTable.Ready_for_OV){
			// Nothing to do
    	}else if(status == NatoCaseStateTable.OV_in_Progress){
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_Edit_to_OV){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.AP_Edit_to_OV){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_in_Progress);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.QC_Edit_to_OV){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_in_Progress);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_OV){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		
    		
    	// Order Entry
		}else if(status == NatoCaseStateTable.Ready_for_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_in_Progress){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Ready_for_OE);
    		UpdateCaseField(cases, 'Order_Entry__c', CreateUser(Role_OE).ID);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.OE_With_Vendor){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		
    	}else if(status == NatoCaseStateTable.OV_Response_to_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_Edit_to_OV);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.QC_Edit_to_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_in_Progress);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.AP_Edit_to_OE){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_in_Progress);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.OE_Release_Live){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    		    		
    	// Ad Production
		}else if(status == NatoCaseStateTable.Ready_for_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Cancelled); // Skip a few states
    		UpdateCaseField(cases, 'Order_Entry__c', CreateUser(Role_OE).ID);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.AP_in_Progress){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Ready_for_AP);
    		UpdateCaseField(cases, 'Ad_Production__c', CreateUser(Role_AP).ID);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		
    	}else if(status == NatoCaseStateTable.OV_Response_to_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_Edit_to_OV);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_Response_to_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_Edit_to_OE);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.QC_Edit_to_AP){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_in_Progress);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.AP_Release_Live){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_in_Progress);
    		UpdateCaseStatus(cases, status, Role_AP);    		

    	// Quality Control
		}else if(status == NatoCaseStateTable.Ready_for_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Cancelled); // Skip a few states
    		//MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseField(cases, 'Order_Entry__c', CreateUser(Role_OE).ID);
    		UpdateCaseField(cases, 'Ad_Production__c', CreateUser(Role_AP).ID);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.QC_in_Progress){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Ready_for_QC);
    		UpdateCaseField(cases, 'Quality_Control__c', CreateUser(Role_QC).ID);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		
    	}else if(status == NatoCaseStateTable.OV_Response_to_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Edit_to_OV);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_Response_to_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Edit_to_OE);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.AP_Response_to_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Edit_to_AP);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.Ready_for_2nd_QC){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Release_Live);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.Site_Issue){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Release_Live);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.QC_Release_Live){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_in_Progress);
    		UpdateCaseStatus(cases, status, Role_QC);    		

    	// Sales Support
		}else if(status == NatoCaseStateTable.OV_Pre_Fulfillment_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OV_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.OE_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OE_in_Progress);
    		UpdateCaseStatus(cases, status, Role_OE);    		
    	}else if(status == NatoCaseStateTable.AP_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.AP_in_Progress);
    		UpdateCaseStatus(cases, status, Role_AP);    		
    	}else if(status == NatoCaseStateTable.QC_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_in_Progress);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.Query_to_Client){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else if(status == NatoCaseStateTable.Billing_Query_to_SS){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Billing_in_Progress);
    		UpdateCaseStatus(cases, status, Role_Billing);    		
    	}else if(status == NatoCaseStateTable.Billing_Complete){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Billing_in_Progress);
    		UpdateCaseStatus(cases, status, Role_Billing);    		
    	}else if(status == NatoCaseStateTable.QC_Fulfilled){
    		MoveCasesToStatus(cases, NatoCaseStateTable.QC_Release_Live);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.SS_With_Vendor){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_Pre_Fulfillment_to_SS);
    		UpdateCaseStatus(cases, status, Role_QC);    		

    	// Billing
		}else if(status == NatoCaseStateTable.Ready_for_Billing){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Cancelled); // Skip a few states
    		//MoveCasesToStatus(cases, NatoCaseStateTable.QC_Release_Live);
    		UpdateCaseStatus(cases, status, Role_QC);    		
    	}else if(status == NatoCaseStateTable.Billing_in_Progress){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Ready_for_Billing);
    		UpdateCaseField(cases, 'Billing__c', CreateUser(Role_Billing).ID);
    		UpdateCaseStatus(cases, status, Role_Billing);    		
    	}else if(status == NatoCaseStateTable.SS_Response_to_Billing){
    		MoveCasesToStatus(cases, NatoCaseStateTable.Billing_Query_to_SS);
    		UpdateCaseStatus(cases, status, Role_SS);    		

		// Other
    	}else if(status == NatoCaseStateTable.Cancelled){
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_in_Progress);
    		MoveCasesToStatus(cases, NatoCaseStateTable.OV_Pre_Fulfillment_to_SS);
    		UpdateCaseStatus(cases, status, Role_OV);    		
    	}else{
    		system.assert(false, 'MoveCasesToStatus does not support status: ' + status);
    	}    	
    	
	}

    private static void UpdateCaseField(List<Case> cases, string fieldName, object value){
    	for(Case c: cases)
    		c.put(fieldname, value);
    }
    private static void UpdateCaseStatus(List<Case> cases, string status, string userRole){
    	system.assert(userRole != null);
    	
    	for(Case c: cases)
    		c.status = status;
    		
 			User u = CreateUser(userRole);
			System.runAs(u){
    			update cases;
			}    		
    }

/*
todo: delete           
    private static void UpdateCaseStatus(List<Case> cases, string ssRep, string ovRep, string oeRep, string apRep, string qcRep, string qc2Rep, string billingRep){
    	system.assert(userRole != null);
    	
    	for(Case c: cases)
			if(null != ssRep)
				c.Nato_Rep_SS__c = ssRep;
				    		
			if(null != ovRep)
				c.NATO_Rep_OV__c = ovRep;

			if(null != oeRep)
				c.Order_Entry__c = oeRep;

			if(null != apRep)
				c.Ad_Production__c = apRep;

			if(null != qcRep)
				c.Quality_Control__c = qcRep;

			if(null != qc2Rep)
				c.Nato_Rep_QC2__c = qc2Rep;

			if(null != billingRep)
				c.Billing__c = billingRep;
				
 			User u = CreateUser(userRole);
			System.runAs(u){
    			update cases;
			}    		
    }
*/
    
    private static User CreateUser(string role){
    	if(!testUsers.ContainsKey(role)){
    		
	    	if(null == natoProfileId)
				natoProfileId = [Select ID from Profile where Name = 'National Operations'][0].ID;
	 
	 		if(null == natoRoleMap){
	 			natoRoleMap = new Map<string, ID>();
	 			List<string> natoRolenames = new List<string> {Role_OE,Role_AP,Role_SS,Role_OV,Role_QC,Role_QC2,Role_Billing,Role_AASSales};
				List<UserRole> roles = [Select ID, Name from UserRole where name in :natoRolenames];
				for(UserRole r: roles)
					natoRoleMap.put(r.Name, r.ID);
	 		}
	 		 
	 		ID roleID = natoRoleMap.get(role);
			System.assert(roleID != null, 'Could load role ID for role: ' + role);
			
	 		string uniqueName = role.replace(' ', '_') + testUsers.size();
	 		
			User user = new User(alias = 'testUser', email='unitTest@attinteractive.com', 
	            emailencodingkey='UTF-8', lastname='Unit Test', languagelocalekey='en_US', 
	            localesidkey='en_US', profileid = natoProfileId, UserRoleId = roleID, 
	            timezonesidkey='America/Los_Angeles', AFrontier_Employee_ID__c= '12345' , username='unitTest@attinteractive.com.unitest.' + uniqueName);
	        
	    	User sysAdmin = [select id from User where Profile.name = 'System Administrator' and isActive = true limit 1];
	    	System.runAs(sysAdmin){
	    		insert user;
	    	}
	    	testUsers.put(role, user);
    	}    	
		return testUsers.get(role);            
    }
}